#pragma once
#include "log.hpp"
#include <brpc/channel.h>


class ServiceChannel {
public:
    using ptr = std::shared_ptr<ServiceChannel>;
    using ChannelPtr = std::shared_ptr<brpc::Channel>;
    ServiceChannel(const std::string& service_name)
        : _service_name(service_name), _idx(0) {}

    //添加Channel
    bool append(const std::string& host) {
        ChannelPtr new_channel = std::make_shared<brpc::Channel>();
        brpc::ChannelOptions options;
        options.connect_timeout_ms = -1;
        options.timeout_ms = -1;
        options.max_retry = 3;
        options.protocol = "baidu_std";
        int ret = new_channel->Init(host.c_str(), &options);
        if(ret < 0) {
            LOG_ERROR("初始化 {} - {} 信道失败", host, _service_name);
            return false;
        }

        std::unique_lock<std::mutex> lock(_mutex);
        _hosts[host] = new_channel;
        _channels.push_back(new_channel);
        return true;
    }

    //服务下线了，则删除Channel
    bool remove(const std::string& host) {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _hosts.find(host);
        if (it == _hosts.end()) {
            LOG_WARN("未找到服务 {} 的信道", host);
            return false;
        }

        ChannelPtr channel = it->second;
        _hosts.erase(it);
        auto vec_it = std::find(_channels.begin(), _channels.end(), channel);
        if (vec_it == _channels.end()) {
            LOG_WARN("未找到服务 {} 的信道", host);
            return false;
        }

        _channels.erase(vec_it);
        return true;
    }


    ChannelPtr choose() {
        std::unique_lock<std::mutex> lock(_mutex);
        if (_channels.empty()) {
            LOG_ERROR("没有可用的信道");
            return nullptr;
        }

        //轮转选择
        ChannelPtr channel = _channels[_idx];
        _idx = (_idx + 1) % _channels.size();
        return channel;
    }

private:
    std::mutex _mutex;
    std::string _service_name;
    //当前轮转的下标
    int _idx;
    //便于rr轮转负载均衡式调度，选用vector
    //当前服务对应的所有Channel
    std::vector<ChannelPtr> _channels;
    //主机地址和Channel的映射
    std::unordered_map<std::string, ChannelPtr> _hosts;
};



class ServiceManager {
public:
    using ptr = std::shared_ptr<ServiceManager>;
    //获取指定服务的信道, 如果没有可用的信道则返回nullptr
    ServiceChannel::ptr choose(const std::string& service_name) {
        std::unique_lock<std::mutex> lock(_mutex);
        for(auto & service : _services) {
            LOG_DEBUG("{}", service.first);
        }
        auto it = _services.find(service_name);
        if (it == _services.end()) {
            LOG_ERROR("当前无节点能提供{}服务", service_name);
            return nullptr;
        }
        return it->second;
    }

    //声明关心的服务
    bool declared(const std::string& service_name) {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _follow_services.find(service_name);
        if(it != _follow_services.end()) {
            LOG_WARN("已关心服务 {}", service_name);
            return true;
        }
        auto pair = _follow_services.insert(service_name);
        if (!pair.second) {
            LOG_ERROR("关心服务 {} 失败", service_name);
            return false;
        }
        return true;
    }


    //当有服务上线时调用的的回调
    void onServiceOnline(const std::string& service_instance, const std::string& host) {
        std::string service_name = getServiceName(service_instance);
        ServiceChannel::ptr ptr; {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _follow_services.find(service_name);
            if (it == _follow_services.end()) {
                LOG_DEBUG("未关心服务 {} - {}，忽略上线事件", service_name, host);
                return;
            }
            auto service_it = _services.find(service_name);
            if(service_it == _services.end()) {
                //没有则新建
                ptr = std::make_shared<ServiceChannel>(service_name);
                _services[service_name] = ptr;
            }
            else {
                ptr = service_it->second;
            }
        }
        ptr->append(host);
        LOG_DEBUG("服务 {} - {} 上线", service_name, host);
    }


    //当有服务下线时调用的的回调
    void onServiceOffline(const std::string& service_instance, const std::string& host) {
        std::string service_name = getServiceName(service_instance);
        std::unordered_map<std::string, ServiceChannel::ptr>::iterator sit; {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _follow_services.find(service_name);
            if (it == _follow_services.end()) {
                LOG_DEBUG("未关心服务 {} - {}，忽略下线事件", service_name, host);
                return;
            }
            sit = _services.find(service_name);
            if(sit == _services.end()) {
                LOG_DEBUG("删除服务 {} - {} 时未找到管理对象", service_name, host);
                return;
            }
        }   
        sit->second->remove(host);
        LOG_DEBUG("{}-{} 服务下线节点", service_name, host);
    }
private:
    std::string getServiceName(const std::string& service_instance) {
        size_t pos = service_instance.find_last_of('/');
        if (pos == std::string::npos) {
            return service_instance; // 如果没有找到斜杠，返回整个字符串
        }
        return service_instance.substr(0, pos); // 返回斜杠之前的部分
    }
private:
    std::mutex _mutex;
    //关心的服务名集合
    std::unordered_set<std::string> _follow_services;
    // 服务名和ServiceChannel的映射
    std::unordered_map<std::string, ServiceChannel::ptr> _services;
};